﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;

namespace AleScheduler
{
    public partial class ExceptionDialog : Form
    {
        public ExceptionDialog()
        {
            InitializeComponent();
        }
#region Overload Costructor
        /// <summary> Costructor Overload for ExceptionDialog Class </summary>
        /// <param name="ex"> Error Exception</param>
        /// <param name="logoImage"> Logo Image of Error to Display in ExceptionDialog</param>
        /// <param name="action"> Custom user action Message : What the User can do for avoid error </param>
        /// <param name="errorDir"> Directory where save the errrolog text files and screenshot image </param>
        /// <param name="emailSMTP"> Adress of eMail SMTP Server for send error notification </param>
        /// <param name="emailPort"> Number of listening port of eMail SMTP Server for send error notification </param>
        /// <param name="emailFrom"> eMail adress of sender for send error notification </param>
        /// <param name="emailTo"> eMail adress of adressee for send error notification </param>
        /// <param name="emailUser"> Username for eMail SMTP Server Authentication </param>
        /// <param name="emailPass"> Password for eMail SMTP Server Authentication </param>
        public ExceptionDialog(Exception ex, Image logoImage, string action, string errorDir,string emailSMTP,int emailPort,string emailFrom,string emailTo,string emailUser,string emailPass)
        {
            InitializeComponent();
            this.errExeption = ex;
            this.errImageLogo = logoImage;
            this.errAction = action;
            this.pathScreenShot = errorDir;
            this.pathTextLog = errorDir;
            this.eMail = true; this.eMail_SMTP = emailSMTP;
            this.eMail_Port = emailPort; this.eMail_fromAddress = emailFrom;
            this.eMail_toAddress = emailTo; this.eMail_Username = emailUser;
            this.eMail_Password = emailPass;
        }
        public ExceptionDialog(Exception ex, Image logoImage, string action, string errorDir, string emailSMTP, int emailPort, string emailFrom, string emailTo)
        {
            InitializeComponent();
            this.errExeption = ex;
            this.errImageLogo = logoImage;
            this.errAction = action;
            this.pathScreenShot = errorDir;
            this.pathTextLog = errorDir;
            this.eMail = true; this.eMail_SMTP = emailSMTP;
            this.eMail_Port = emailPort; this.eMail_fromAddress = emailFrom;
            this.eMail_toAddress = emailTo;
        }
        public ExceptionDialog(Exception ex, Image logoImage, string action, string errorDir, string emailSMTP, string emailFrom, string emailTo)
        {
            InitializeComponent();
            this.errExeption = ex;
            this.errImageLogo = logoImage;
            this.errAction = action;
            this.pathScreenShot = errorDir;
            this.pathTextLog = errorDir;
            this.eMail = true; this.eMail_SMTP = emailSMTP;
            this.eMail_fromAddress = emailFrom;
            this.eMail_toAddress = emailTo;
        }
        public ExceptionDialog(Exception ex, Image logoImage, string action, string errorDir)
        {
            InitializeComponent();
            this.errExeption = ex;
            this.errImageLogo = logoImage;
            this.errAction = action;
            this.pathScreenShot = errorDir;
            this.pathTextLog = errorDir;
            this.eMail = false;
        }
        public ExceptionDialog(Exception ex, Image logoImage, string action)
        {
            InitializeComponent();
            this.errExeption = ex;
            this.errImageLogo = logoImage;
            this.errAction = action;
            this.eMail = false;
        }
        public ExceptionDialog(Exception ex, Image logoImage)
        {
            InitializeComponent();
            this.errExeption = ex;
            this.errImageLogo = logoImage;
            this.eMail = false;
        }
#endregion

        PerformanceCounter cpuCounter;
        PerformanceCounter ramCounter;
        public string errMessage { get; set; }
        public string errDescription { get; set; }
        public string errAction { get; set; }
        public string errstacTrace { get; set; }
        public Image errImageLogo { get; set; }
        public Exception errExeption { get; set; }
        public string pathScreenShot { get; set; }
        public string pathTextLog { get; set; }
        public bool eMail = false;
        public string eMail_SMTP { get; set; }
        public string eMail_fromAddress { get; set; }
        public string eMail_toAddress { get; set; }
        public int eMail_Port { get; set; }
        public string eMail_Username { get; set; }
        public string eMail_Password { get; set; }
        public string eMail_Attachment { get; set; }

        const int _intSpacing = 10;
        private void btnMore_Click(object sender, EventArgs e)
        {
            if (btnMore.Text == ">>")
            {
                this.Height = this.Height + 300;

                txtMore.Location = new System.Drawing.Point(lblMoreHeading.Left, lblMoreHeading.Top + lblMoreHeading.Height + _intSpacing);
                txtMore.Height = this.ClientSize.Height - txtMore.Top - 45;
                txtMore.Width = this.ClientSize.Width - 2 * _intSpacing;
                txtMore.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
                txtMore.Visible = true;

                btnMore.Text = "<<";
            }
            else
            {
                this.SuspendLayout();
                btnMore.Text = ">>";
                this.Height = btnMore.Top + btnMore.Height + _intSpacing + 45;
                txtMore.Visible = false;
                txtMore.Anchor = System.Windows.Forms.AnchorStyles.None;
                this.ResumeLayout();
            }
        }

        private void ExceptionDialog_Load(object sender, EventArgs e)
        {
            //Performance Monitor Initialization
            cpuCounter = new PerformanceCounter();
            cpuCounter.CategoryName = "Processor";
            cpuCounter.CounterName = "% Processor Time";
            cpuCounter.InstanceName = "_Total";
            ramCounter = new PerformanceCounter("Memory", "Available MBytes");

            //Set Form Title 
            this.Text = Application.ProductName + " - Exception";

            //Error property Setting
            if(!string.IsNullOrEmpty(this.errMessage))
            this.ErrorBox.Text = this.errMessage;
            if (!string.IsNullOrEmpty(this.errAction))
            this.ActionBox.Text = this.errAction;

            //ImageLogo Settings
            if (this.errImageLogo != null)
                this.PictureBoxError.Image = this.errImageLogo;

            //Take a ScreenShot
            this.eMail_Attachment = this.pathScreenShot + System.IO.Path.DirectorySeparatorChar + Application.ProductName + "_" + this.TimeStamp + ".png";
            if(!string.IsNullOrEmpty(this.pathScreenShot))
                this.SaveScreenShot(this.eMail_Attachment, System.Drawing.Imaging.ImageFormat.Png);

            //More Information
            this.txtMore.Text = string.Empty;
            this.txtMore.Text += "Date                 : " + DateTime.Now.ToLongDateString();
            this.txtMore.Text += Environment.NewLine;
            this.txtMore.Text += "Time                 : " + DateTime.Now.ToLongTimeString();
            if (!string.IsNullOrEmpty(this.pathScreenShot))
            {
                this.txtMore.Text += Environment.NewLine;
                this.txtMore.Text += "Screenshot           : " + this.eMail_Attachment;
            }
            this.txtMore.Text += Environment.NewLine; this.txtMore.Text += Environment.NewLine;

            this.txtMore.Text += "---- Application ---- ";
            this.txtMore.Text += Environment.NewLine;
            this.txtMore.Text += "Name                 : " + Application.ProductName;
            this.txtMore.Text += Environment.NewLine;
            this.txtMore.Text += "Version              : " + Application.ProductVersion;
            this.txtMore.Text += Environment.NewLine;
            this.txtMore.Text += "Startup Path         : " + Application.StartupPath;
            this.txtMore.Text += Environment.NewLine;
            this.txtMore.Text += "Commandline Args     : " + Environment.CommandLine;
            this.txtMore.Text += Environment.NewLine; this.txtMore.Text += Environment.NewLine;

            this.txtMore.Text += "---- System Enviroment ---- ";
            this.txtMore.Text += Environment.NewLine;
            this.txtMore.Text += "CPU Usage            : " + this.CPUsage;
            this.txtMore.Text += Environment.NewLine;
            this.txtMore.Text += "RAM Usage            : " + this.RAMUsage;
            this.txtMore.Text += Environment.NewLine;
            this.txtMore.Text += "OS                   : " + Environment.OSVersion;
            this.txtMore.Text += Environment.NewLine;
            this.txtMore.Text += "Memory WorkingSet    : " + Environment.WorkingSet;
            this.txtMore.Text += Environment.NewLine;
            this.txtMore.Text += "Username             : " + Environment.UserName;
            this.txtMore.Text += Environment.NewLine;
            this.txtMore.Text += "Hostname             : " + this.Hostname;
            this.txtMore.Text += Environment.NewLine;
            string[] ip = this.getIPAddress();
            string ipList = string.Empty;
            for (int i = 0; i < ip.Length; i++)
            {
                ipList += " " + ip[i].ToString();
            }
            this.txtMore.Text += "IP                   :" + ipList;
            this.txtMore.Text += Environment.NewLine;
            this.txtMore.Text += "System Path          : " + Environment.GetEnvironmentVariable("Path");
            this.txtMore.Text += Environment.NewLine; this.txtMore.Text += Environment.NewLine;

            this.txtMore.Text += "---- Exception Information ---- ";
            this.txtMore.Text += Environment.NewLine;
            if (this.errExeption != null)
            {
                this.txtMore.Text += "Exception Source : " + errExeption.Source;
                this.txtMore.Text += Environment.NewLine;
                this.txtMore.Text += "Exception Type   : " + errExeption.GetType().ToString();
                this.txtMore.Text += Environment.NewLine;
                this.txtMore.Text += "Exception Message: " + errExeption.Message;
                this.txtMore.Text += Environment.NewLine;
                this.txtMore.Text += "Exception Target : " + errExeption.TargetSite;
                this.txtMore.Text += Environment.NewLine; this.txtMore.Text += Environment.NewLine;

                this.txtMore.Text += "---- Stack Trace ----";
                this.txtMore.Text += Environment.NewLine;
                this.txtMore.Text += errExeption.StackTrace;

                //Set Other Textbox
                this.DescriptionBox.Text = errExeption.GetType().ToString() + " : " + errExeption.Message;
            }

            //Save a Text log files in a specified directory
            if (!string.IsNullOrEmpty(this.pathTextLog) && System.IO.Directory.Exists(this.pathTextLog))
                System.IO.File.WriteAllText(this.pathTextLog + System.IO.Path.DirectorySeparatorChar +
                    Application.ProductName + "_" + this.TimeStamp + ".log", this.txtMore.Text);

            //Final Settings
            this.btneMail.Visible = this.eMail;
            this.TopMost = true;
            this.Height = this.btnMore.Top + this.btnMore.Height + _intSpacing + 45;

            //Write in Event Log
            EventLog log = new EventLog();
            if (!EventLog.SourceExists(Application.ProductName))
                EventLog.CreateEventSource(Application.ProductName,"Application");

            log.Source = Application.ProductName;
            log.WriteEntry(this.txtMore.Text,EventLogEntryType.Error);
        }

        #region Utility Function
        //GetTimestamp Function
        public string TimeStamp
        {
            get
            {
                return GetTimestamp(DateTime.Now);
            }
        }

        private string GetTimestamp(DateTime value)
        {
            return value.ToString("yyyyMMddHHmmssffff");
        }

        //Get Hostname 
        public string Hostname
        {
            get
            {
                return System.Net.Dns.GetHostName();
            }
        }
        //Get IP Address
        public string[] getIPAddress()
        {
            System.Net.IPHostEntry ipEntry = System.Net.Dns.GetHostByName(this.Hostname);
            System.Net.IPAddress[] addr = ipEntry.AddressList;
            string[] atmp = new string[addr.Length];

            for (int i = 0; i < addr.Length; i++)
            {
                atmp[i] = addr[i].ToString();
            }
            return atmp;
        }
        //CPU and RAM Usage
        private string CPUsage
        {
            get
            {
                return cpuCounter.NextValue() + " %";
            }
        }
        private string RAMUsage
        {
            get
            {
                return ramCounter.NextValue() + " MB";
            }
        }

        //Send eMail of Error
        /// <summary> Method for send an eMail Notification </summary>
        /// <param name="from"> eMail Adress from</param>
        /// <param name="to"> eMail address of adressee</param>
        /// <param name="smtp"> Smtp Server Address</param>
        private bool SendeMail(string from,string to,string smtp)
        {
            System.Net.Mail.MailMessage msg = new System.Net.Mail.MailMessage(new System.Net.Mail.MailAddress(from), new System.Net.Mail.MailAddress(to));    //  Create a MailMessage object with a from and to address
            msg.Subject = Application.ProductName + " - " + this.errExeption.GetType().ToString();  //  Add your subject
            msg.SubjectEncoding = System.Text.Encoding.UTF8;
            msg.Body = this.txtMore.Text;    //  Add the body of your message
            msg.BodyEncoding = System.Text.Encoding.UTF8;
            msg.IsBodyHtml = false; //  Does the body contain html
            if(!string.IsNullOrEmpty(this.eMail_Attachment) && System.IO.File.Exists(this.eMail_Attachment))
            {
            System.Net.Mail.Attachment attachFile = new System.Net.Mail.Attachment(this.eMail_Attachment);
            msg.Attachments.Add(attachFile);
            }
            System.Net.Mail.SmtpClient client = new System.Net.Mail.SmtpClient(smtp, 25); //  Create an instance of SmtpClient with your smtp host and port

            try
            {
                client.Send(msg);//  Try to send your message
                return true;
            }
            catch (Exception ex)
            {
                Debug.Print(ex.Message);
                return false;
            }
        }
        /// <summary> Method for send an eMail Notification </summary>
        /// <param name="from"> eMail Adress from</param>
        /// <param name="to"> eMail address of adressee</param>
        /// <param name="smtp"> Smtp Server Address</param>
        /// <param name="port"> Smtp Server Number of Port</param>
        private bool SendeMail(string from, string to, string smtp,int port)
        {
            System.Net.Mail.MailMessage msg = new System.Net.Mail.MailMessage(new System.Net.Mail.MailAddress(from), new System.Net.Mail.MailAddress(to));    //  Create a MailMessage object with a from and to address
            msg.Subject = Application.ProductName + " - " + this.errExeption.GetType().ToString();  //  Add your subject
            msg.SubjectEncoding = System.Text.Encoding.UTF8;
            msg.Body = this.txtMore.Text;    //  Add the body of your message
            msg.BodyEncoding = System.Text.Encoding.UTF8;
            msg.IsBodyHtml = false; //  Does the body contain html
            if (!string.IsNullOrEmpty(this.eMail_Attachment) && System.IO.File.Exists(this.eMail_Attachment))
            {
                System.Net.Mail.Attachment attachFile = new System.Net.Mail.Attachment(this.eMail_Attachment);
                msg.Attachments.Add(attachFile);
            }
            System.Net.Mail.SmtpClient client = new System.Net.Mail.SmtpClient(smtp, port); //  Create an instance of SmtpClient with your smtp host and port

            try
            {
                client.Send(msg);//  Try to send your message
                return true;
            }
            catch (Exception ex)
            {
                Debug.Print(ex.Message);
                return false;
            }
        }
        /// <summary> Method for send an eMail Notification </summary>
        /// <param name="from"> eMail Adress from</param>
        /// <param name="to"> eMail address of adressee</param>
        /// <param name="smtp"> Smtp Server Address</param>
        /// <param name="port"> Smtp Server Number of Port</param>
        /// <param name="username"> Smtp Server Username for Authentication</param>
        /// <param name="password"> Smtp Server Password for Authentication</param>
        private bool SendeMail(string from, string to, string smtp, int port,string username,string password)
        {
            System.Net.Mail.MailMessage msg = new System.Net.Mail.MailMessage(new System.Net.Mail.MailAddress(from), new System.Net.Mail.MailAddress(to));    //  Create a MailMessage object with a from and to address
            msg.Subject = Application.ProductName + " - " + this.errExeption.GetType().ToString();  //  Add your subject
            msg.SubjectEncoding = System.Text.Encoding.UTF8;
            msg.Body = this.txtMore.Text;    //  Add the body of your message
            msg.BodyEncoding = System.Text.Encoding.UTF8;
            msg.IsBodyHtml = false; //  Does the body contain html
            if (!string.IsNullOrEmpty(this.eMail_Attachment) && System.IO.File.Exists(this.eMail_Attachment))
            {
                System.Net.Mail.Attachment attachFile = new System.Net.Mail.Attachment(this.eMail_Attachment);
                msg.Attachments.Add(attachFile);
            }
            System.Net.Mail.SmtpClient client = new System.Net.Mail.SmtpClient(smtp, port); //  Create an instance of SmtpClient with your smtp host and port
            if (username != string.Empty && password != string.Empty)
            {

                client.Credentials = new System.Net.NetworkCredential(username, password); //  Assign your username and password to connect to gmail
                client.EnableSsl = true;  //  Enable SSL
            }
            try
            {
                client.Send(msg);//  Try to send your message
                return true;
            }
            catch (Exception ex)
            {
                Debug.Print(ex.Message);
                return false;
            }
        }
        #endregion

        #region Region Screen Capture Method
        /// <summary>
        /// Saves a screen capture in the specified image format to a file.
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="format"></param>
        private void SaveScreenShot(string filename, System.Drawing.Imaging.ImageFormat format)
        {
            Bitmap screenShot = CaptureScreenShot();

            screenShot.Save(filename, format);
        }

        /// <summary>
        /// Saves a picture of the screen to a bitmap image.
        /// </summary>
        /// <returns>The saved bitmap.</returns>
        private Bitmap CaptureScreenShot()
        {
            // get the bounding area of the screen containing (0,0)
            // remember in a multidisplay environment you don't know which display holds this point
            Rectangle bounds = Screen.GetBounds(Point.Empty);

            // create the bitmap to copy the screen shot to
            Bitmap bitmap = new Bitmap(bounds.Width, bounds.Height);

            // now copy the screen image to the graphics device from the bitmap
            using (Graphics gr = Graphics.FromImage(bitmap))
            {
                gr.CopyFromScreen(Point.Empty, Point.Empty, bounds.Size);
            }

            return bitmap;
        }

        /// <summary>
        /// Saves a screen capture of the specified control to a file.
        /// </summary>
        /// <param name="control"></param>
        /// <param name="filename"></param>
        /// <param name="format"></param>
        private void SaveControlShot(Control control, string filename, System.Drawing.Imaging.ImageFormat format)
        {
            Bitmap controlShot = CaptureControlShot(control);

            controlShot.Save(filename, format);
        }

        /// <summary>
        /// Gets a bitmap image of the specified control.
        /// </summary>
        /// <param name="control"></param>
        /// <returns></returns>
        private Bitmap CaptureControlShot(Control control)
        {
            // get control bounding rectangle
            Rectangle bounds = control.Bounds;

            // create the new bitmap that holds the image of the control
            Bitmap bitmap = new Bitmap(bounds.Width, bounds.Height);

            // copy controls image data to the bitmaps graphics device
            using (Graphics gr = Graphics.FromImage(bitmap))
            {
                gr.CopyFromScreen(control.Location, Point.Empty, bounds.Size);
            }

            return bitmap;
        }

#endregion

        private void btnOK_Click(object sender, EventArgs e)
        {
            //All Application Close
            Application.Exit();
        }

        private void btneMail_Click(object sender, EventArgs e)
        {
            if (this.eMail)
            {
                bool esito = false;
                //Send eMail
                if(!string.IsNullOrEmpty(this.eMail_fromAddress) & !string.IsNullOrEmpty(this.eMail_toAddress) & !string.IsNullOrEmpty(this.eMail_SMTP) & !string.IsNullOrEmpty(this.eMail_Username) & !string.IsNullOrEmpty(this.eMail_Password))
                    esito = this.SendeMail(this.eMail_fromAddress, this.eMail_toAddress, this.eMail_SMTP, this.eMail_Port, this.eMail_Username, this.eMail_Password);
                else if (!string.IsNullOrEmpty(this.eMail_fromAddress) & !string.IsNullOrEmpty(this.eMail_toAddress) & !string.IsNullOrEmpty(this.eMail_SMTP))
                esito = this.SendeMail(this.eMail_fromAddress, this.eMail_toAddress, this.eMail_SMTP);


                if (esito)
                    MessageBox.Show("Message Sent", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information);
                else
                    MessageBox.Show("Couldn't send message !", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void txtMore_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                //Create a Context Menu
                ContextMenu mnuContextMenu = new ContextMenu();
                this.txtMore.ContextMenu = mnuContextMenu;
                MenuItem mnuItemSetting = new MenuItem();
                mnuItemSetting.Text = "Save LOG File";
                mnuContextMenu.MenuItems.Add(mnuItemSetting);
                mnuItemSetting.Click += new EventHandler(btnSave_Click);
            }
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            SaveFileDialog sv = new SaveFileDialog();
            sv.InitialDirectory = Application.StartupPath;
            sv.Title = "Save Error Dump - " + Application.ProductName;
            sv.FileName = Application.ProductName + "_" + this.TimeStamp + ".log";
            if (sv.ShowDialog() == DialogResult.OK)
            {
                //Save log Text File
                System.IO.File.WriteAllText(sv.FileName, this.txtMore.Text);
            }
        }

        private void txtMore_DoubleClick(object sender, EventArgs e)
        {
            btnSave_Click(sender, e);
        }

    }
}
